#include "bsp_api.h" 
#include "sdp800.h"
#include <stdint.h>
#include <math.h>
#include <pca9555.h>
#include "ad7708.h"
#include "pca9538.h"
#include "modbus.h"
#include "los_base.h"
#include "los_task.ph"
#include "los_typedef.h"
#include "los_sys.h"
#include "read_and_write_flash.h"
#include "bsp.h"
#include "usart.h"
#include "app_common.h"
#include "mcu_log.h"
//#define READ_AI
extern UINT8 vav_get_point_priority_by_stype(char *sensor_type);

uint8_t  g_mode = 0; //主设备还是从设备模式

typedef struct _DEV_STATUS 	//设备状态
{
	float		panel_set_temp;			//面板的设置温度
	float		panel_set_temp_tag;		//面板的设置温度目标值
	float		panel_env_temp;		//面板的环境温度
	int			panel_status;		//面板的状态值
	int			panel_status_tag;		//面板的状态目标值
	int			panel_unit;			//面板的什么?
	double		pressure; 			//压差传感器数据
	double		valve_degree; 		//阀门开度
	
	uint8_t		panel_set_temp_err;	//读取面板设置温度时的错误码
	uint8_t		panel_env_temp_err;	//读取面板环境温度时的错误码
	uint8_t		panel_status_err;	//读取面板状态值时的错误码
}DEV_STATUS;

typedef struct _SAVE_STATUS //设备要保存到FLASH的状态
{
	char		flash_sign[16];		//flash已存储标志
	float 		sum_degree;			//风阀累计旋转角度
	uint32_t 	sum_count;			//风阀累计旋转次数
	uint8_t		is_changed;			//是否有改变
}SAVE_STATUS;

typedef struct _CALI_DATA //风阀校准数据
{
	uint16_t	valve_ad_max; 		//风阀最大限位的AD值
	uint16_t	valve_ad_min; 		//风阀最小限位的AD值
	uint8_t		is_calied;			//风阀是否校准完毕
}CALI_DATA;

typedef struct res_to_temp //风阀校准数据
{
	uint8_t	temp; 		//风阀最大限位的AD值
	int	resistor; 		//风阀最小限位的AD值
}res_to_temp_t;


extern int g_update_flag;
static CALI_DATA	g_cali_data ={0};	//风阀校准数据
static DEV_STATUS	g_dev_status ={0};	//设备状态
static SAVE_STATUS	g_sava_status ={0};	//设备要保存到FLASH的状态
static int 		target_degree = 0; //目标开度
static int 		motor_running = 0; //是否需要控制阀门
static uint8_t g_motor_output = 30;

double read_pressure() //读取压差传感器数据
{
	static int lstTime =0; 				//上次复位时间
	static unsigned char lstStatus =0;	//上次的步骤状态
	int curTime =LOS_Tick2MS(LOS_TickCountGet()); //当前时间
	if(abs(curTime -lstTime) <200) return g_dev_status.pressure; //时间间隔还没到
	if(lstStatus==0) //第一步
	{
	    Sdp800_SoftReset();
		Error error =Sdp800_StartContinousMeasurement(SDP800_TEMPCOMP_MASS_FLOW, SDP800_AVERAGING_TILL_READ);
		if(ERROR_NONE ==error) {lstTime =curTime; lstStatus =1;} //正常
		else				   {return (double)0;} //有错误
	}
	else if(abs(curTime -lstTime) >=1000)
	{
		float diffPressure =0, temperature =0;
		Error error = Sdp800_ReadMeasurementResults(&diffPressure, &temperature);
		if(ERROR_NONE ==error) {lstTime =curTime; lstStatus =0;} //正常
		else				   {return (double)0;} //有错误
		return ((double)diffPressure);
	}
	return g_dev_status.pressure;
}

void vav_set_motor_output(uint8_t motor_output)
{
	if(motor_output < 30 || motor_output > 100) {
		return;
	}
	g_motor_output = motor_output;
	return;
}

void vav_set_motor_dir(uint8_t motor_dir) //控制电机转向
{
    MOTOR_CTL(motor_dir,(100-g_motor_output));
}

void vav_motor_stop() //电机停转
{
    MOTOR_CTL(0,100);
}

void vav_read_ai(uint8_t channel, uint8_t signal) //读取AI
{
	float Rs_f =0;
	uint32_t mV =0, mI =0, Rs =0;
	int p1 =0, p2 =0, p3 =0, ad_ch =0, adcvalue =0;
	switch (channel) {
	case 1:
		p1 =00;	p2 =01;	p3 =02;
		ad_ch = USR_CHANNEL2;
		break;
	case 2:
		p1 =03;	p2 =04;	p3 =05;
		ad_ch = USR_CHANNEL3;
		break;
	case 3:
		p1 =06;	p2 =07;	p3 =010;
		ad_ch = USR_CHANNEL4;
		break;
	}
	switch (signal) {
    case 1: //AI_VOLTAGE_0-10V
		pca9555_setbit(p1, 0);
		pca9555_setbit(p2, 0);
		pca9555_setbit(p3, 0);
		LOS_TaskDelay(500);
		adcvalue = ad7708_read_value(ad_ch);
		mV = (uint32_t)adcvalue*2500/65535;
		mV = mV*145/30;
		printf("[%d,%d,%d]mV:%u\r\n",p1,p2,p3,(unsigned int)mV);
		break;
    case 2: //AI_ELECTRIC_CURRENT_4-20mA
		pca9555_setbit(p1, 0);
		pca9555_setbit(p2, 0);
		pca9555_setbit(p3, 1);
		LOS_TaskDelay(500);
		adcvalue = ad7708_read_value(ad_ch);
		mV = (uint32_t)adcvalue*2500/65535;
		mI = mV*145/30;
		printf("[%d,%d,%d]mV:%u,mI:%u\r\n",p1,p2,p3,(unsigned int)mV,(unsigned int)mI);
		break;
    case 3: //AI_RT_NICKEL_1K_RTD_JCI
		pca9555_setbit(p1, 0);
		pca9555_setbit(p2, 1);
		pca9555_setbit(p3, 0);
		LOS_TaskDelay(500);
		adcvalue = ad7708_read_value(ad_ch);
		mV = (uint32_t)adcvalue*2500/65535;
		Rs = 29*15000*mV/(72000-29*mV);
		Rs_f = (FLOAT)Rs/(145000-Rs);
		Rs = Rs_f*145000;
		printf("[%d,%d,%d]mV:%u,Rs:%u\r\n",p1,p2,p3,(unsigned int)mV,(unsigned int)Rs);
		break;
    default:
		printf("[%s:%d]cannot find signal type.",__FUNCTION__,__LINE__);
		break;
	}
}

void vav_read_bi(uint8_t channel) //读取BI
{
    int p1 =0, p2 =0, p3 =0;
	switch (channel) {
    case 1:
		p1 =00;	p2 =01;	p3 =02;
		break;
    case 2:
		p1 =03;	p2 =04;	p3 =05;
		break;
    case 3:
		p1 =06;	p2 =07;	p3 =010;
		break;
  	}
    pca9555_setbit(p1,1);
    pca9555_setbit(p2,0);
    pca9555_setbit(p3,0);
}

double get_valve_degree() //获取风阀实时开度
{
    double   ret =0;
	uint16_t adVal =ad7708_read_value(USR_CHANNEL1);
	if(adVal >g_cali_data.valve_ad_max)			adVal =g_cali_data.valve_ad_max;
	else if(adVal <g_cali_data.valve_ad_min)	adVal =g_cali_data.valve_ad_min;
	if(g_cali_data.valve_ad_max >g_cali_data.valve_ad_min)
		ret = 100-(100.0f*(adVal-g_cali_data.valve_ad_min)/(g_cali_data.valve_ad_max-g_cali_data.valve_ad_min));
	else
		ret = 100-(100.0f*(adVal/520-3)/103);
	if(ret <=1.1f)			ret =0;
	else if(ret >=98.9f)	ret =100;
    return ret;
}

uint8_t get_switch(uint8_t *datatemp) //读取拨码开关
{
	for(int i = 0; i < 3; i++)
	{
		Error err = pca9538_read_inputdata(datatemp);
		if(ERROR_NONE == err) {
			OMIP_LOG_INFO("read switch value: 0x%02X.\r\n", (int)*datatemp); 
			return *datatemp;
		}
		OMIP_LOG_ERROR_FLASH("[%s:%d]read switch value error(%d)!\r\n",__FUNCTION__,__LINE__,(int)err);
		LOS_TaskDelay(200);
	}
	return 0;
}

void motor_task() //阀门控制线程
{
	float fLstDegree =-9999; //上次控制时阀门的开度
	int	  lstTime =LOS_Tick2MS(LOS_TickCountGet()); //上次控制时间
	vav_motor_stop();
	osal_task_sleep(10000);
	OMIP_LOG_INFO("%s task(%d) start!!!", __FUNCTION__, LOS_CurTaskIDGet());
    while(1)
    {
        osal_task_sleep(50);
        if(!motor_running)	continue; //不需要控制阀门时motor task线程直接continue，避免频繁调用驱动消耗资源
        float fNowDegree  = (float)vav_get_valve_degree(); 	//当前开度
        float fDiffDegree =fNowDegree -target_degree;		//当前开度与目标开度之间的差异
        int curTime =LOS_Tick2MS(LOS_TickCountGet()); 		//当前时间
        if((target_degree==0 &&fabs(fDiffDegree*10)<=2) ||(target_degree >0 &&fabs(fDiffDegree*10)<20)) //已经到达目标，停止电机
		{
			if(fabs(fLstDegree-(-9999)) >1) //刚到达设定位置
			{
				vav_add_sum_count(1);
				OMIP_LOG_INFO("ctrl motor finished![degree:%d(x1000)]\r\n",(int)(fNowDegree*1000));
			}
			vav_motor_stop();
			//恢复30%输出
			vav_set_motor_output(30);
			motor_running =0;
			fLstDegree =-9999; 
		}
		else if(abs(curTime -lstTime) >5000) //与目标还有差异，并且控制时间有了一定间隔
        {
        	lstTime =curTime;
			unsigned char iDir =(fDiffDegree<0? MOTOR_REV:MOTOR_FOWARD);
			if(fabs(fLstDegree-fNowDegree) <2.0f) //电机已经到达限位,要等一段时间电机放电
			{
				OMIP_LOG_INFO("ctrl motor: have a rest!\r\n");
				fLstDegree =-9999;
				vav_motor_stop();
				//卡住时，以60%输出
				vav_set_motor_output(60); 
				osal_task_sleep(10000);
			}
			else //电机还在转动
			{
				fLstDegree = fNowDegree;
				vav_set_motor_dir(iDir); //以30%速度转动电机
			}
        }
    }
}

void set_target_degree(int degree) //设置阀门目标值
{
	int lasttarget_degree = target_degree;
	motor_running =1;
	target_degree = degree; //将阀门的目标值设置为该值
	if(lasttarget_degree != target_degree) {
		OMIP_LOG_INFO( "target degree: %d\r\n", target_degree);
	}
}


void pca9555_in5_init()
{
	uint8_t error = 0;
	
	for(int i = 0; i < 5; i++) 
	{
		error = ERROR_NONE;
		error |= pca9555_init();
		error =  pca9555_setbit(8, 0);
		error |=  pca9555_setbit(7, 1);
		error |=  pca9555_setbit(6, 0);
		if(ERROR_NONE == error) {
			OMIP_LOG_INFO("port in3 init enable successful");
			return;
		}
	}
	OMIP_LOG_ERROR("port in3 init enable failed");
	return;
}

float get_in3_resistor()
{
	uint16_t i_adcvalue = ad7708_read_value(USR_CHANNEL2);
	uint32_t vs= 0,Rs;
	float Rs_f;
	vs = (uint32_t)i_adcvalue*2500/65535;
	Rs = 29*15000*vs/(72000-29*vs);
	Rs_f = (FLOAT)Rs/(145000-Rs);
	Rs = Rs_f*145000;
	Rs = Rs * 1.09 - 115;

	//printf("channel_2 adcval = %d, voltage = %dmV,resistor = %dR\r\n",i_adcvalue,(uint32_t)i_adcvalue*2500/65535,Rs);

	return Rs;
}

float resistor_to_temp_math(float resistor)
{
	/*+∞ ~ 40C*/
	if(resistor < 10457) {
		return (float)(-25.11 * log(resistor) + 272.79);
	}
	/*39 ~35*/
	else if(resistor > 10456 && resistor < 13788) {
		return (float)(-24.35 * log(resistor) + 265.73);
	}
	/*34 ~30*/
	else if(resistor > 12859 && resistor < 17005) {
	 	return (float)(-23.68 * log(resistor) + 259.33);
	}
	/*29C ~ 25*/
	else if(resistor > 15907  && resistor < 21120) {
		return (float)(-23 * log(resistor) + 252.78);
	}
	/*24 ~ 20*/
	else if(resistor > 21119 && resistor < 24696) {
		return (float)(-22.34 * log(resistor) + 246.19);
	}
	/*19 ~ 15*/
	else if(resistor > 24695 && resistor < 33468) {
		return (float)(-21.68 * log(resistor) + 239.55);
	}
	/*14 ~ 10*/
	else if(resistor > 33467 && resistor < 42580) {
		return (float)(-21.04 * log(resistor) +  232.86);
	}
	/*9 ~ -∞*/
	else if(resistor > 42579) {
		return (float)(-20.08 * log(resistor) +  222.68);
	}
	
	return -1.0;

}

void worker_thread_master() //主设备读取温控面板数据线程
{
	
	LED_RS485_2_(LED_CLOSE);
	LED_RS485_1_(LED_CLOSE);
	int lstTime =LOS_Tick2MS(LOS_TickCountGet());
	int updateStartTime = 0;
	int set_tmp = 0.0;
	uint8_t priority = 0;

	OMIP_LOG_INFO("worker_thread_master start!!!!!!!\r\n");
    while(true)
    {
		int curTime = LOS_Tick2MS(LOS_TickCountGet());
		if(g_update_flag) { //升级状态
			if(0 != updateStartTime) {
				updateStartTime = LOS_Tick2MS(LOS_TickCountGet());
			}
			if(abs(curTime - updateStartTime) > (1000*60*10)) { //10分钟升级超时
				g_update_flag = 0;
				OMIP_LOG_DEBUG("[%s:%d] update timeout 10min\r\n",__FUNCTION__,__LINE__);
			}
			continue;
		} 
		else {
			updateStartTime= 0;
		}
		
        float temp = getCtrlPanelEnvTemp(0x01);
        if(abs(temp-INVALID_DATA)>2) {g_dev_status.panel_env_temp_err =0; g_dev_status.panel_env_temp =temp;} //读取值正常
		else						 {g_dev_status.panel_env_temp_err =1;} //读取值错误
        LOS_TaskDelay(1000);
        temp =getCtrlPanelSetTemp(0x01);
		
        if(abs(temp-INVALID_DATA)>2) { //读取值正常
			g_dev_status.panel_set_temp_err =0; 
			g_dev_status.panel_set_temp =temp;			
		} 
		else { //读取值错误
			g_dev_status.panel_set_temp_err =1;
		} 
	    LOS_TaskDelay(1000);
		
	    temp =getCtrlPanelStatus(0x01);
	    if(abs(temp-INVALID_DATA)>2) { //读取值正常
			g_dev_status.panel_status_err =0; 
			g_dev_status.panel_status =temp;
		} 
		else { //读取值错误
			g_dev_status.panel_status_err =1;
		} 
    	LOS_TaskDelay(1000);

		//开关状态同步
		priority = vav_get_point_priority_by_stype("BI-STATUS");
		if(priority > 0 && priority < 16) {
			if(g_dev_status.panel_status != g_dev_status.panel_status_tag) {
				OMIP_LOG_INFO("Write panel status(%d).", g_dev_status.panel_status_tag);
				set_panel_status(1, g_dev_status.panel_status_tag);
			}
		}
		
		LOS_TaskDelay(1000);
		//设置温度同步
		priority = vav_get_point_priority_by_stype("AI-TSP");
		if(priority > 0 && priority < 16) {
			set_tmp = (g_dev_status.panel_set_temp*1000) - (g_dev_status.panel_set_temp_tag*1000);
			if(abs(set_tmp) > 900 && g_dev_status.panel_set_temp_tag != 0) {
				OMIP_LOG_INFO("Write panel set tepm(%d).", (int)g_dev_status.panel_set_temp_tag);
				set_panel_temp(1, g_dev_status.panel_set_temp_tag);
			}
		}
		
		LOS_TaskDelay(1000);
		if(abs(curTime-lstTime)>30000)
		{
			lstTime =curTime;
			OMIP_LOG_INFO("envTemp:%d(x1000), setTemp:%d(x1000), status:%d\r\n", (int)(g_dev_status.panel_env_temp*1000), (int)(g_dev_status.panel_set_temp*1000),g_dev_status.panel_status);
		}
#ifdef READ_AI
		vav_read_ai(1,1);
		LOS_TaskDelay(30);
		vav_read_ai(1,2);
		LOS_TaskDelay(30);
		vav_read_ai(1,3);
		LOS_TaskDelay(30);
		vav_read_ai(2,1);
		LOS_TaskDelay(30);
		vav_read_ai(2,2);
		LOS_TaskDelay(30);
		vav_read_ai(2,3);
		LOS_TaskDelay(30);
		vav_read_ai(3,1);
		LOS_TaskDelay(30);
		vav_read_ai(3,2);
		LOS_TaskDelay(30);
		vav_read_ai(3,3);
#endif
    }
}

void worker_thread_slave() //从设备读取温控面板数据线程
{
	LED_RS485_1_(LED_CLOSE);
	LED_RS485_2_(LED_CLOSE);
	
	int lstTime =LOS_Tick2MS(LOS_TickCountGet());
	OMIP_LOG_INFO("worker_thread_slave start!!!!!!!\r\n");
    while(true) 
    {
		
		LOS_TaskDelay(200);
		if(check_uart_data(USART3) >= 15) {
			slave_uart_recv_process(USART3);
		}

		if(check_uart_data(USART1) >= 15) {
			slave_uart_recv_process(USART1);
		}
		
		int curTime = LOS_Tick2MS(LOS_TickCountGet());
		if(abs(curTime-lstTime)>30000) {
			lstTime =curTime;
			OMIP_LOG_INFO("envTemp:%d(x1000), setTemp:%d(x1000), status:%d\r\n", (int)(g_dev_status.panel_env_temp*1000),(int)(g_dev_status.panel_set_temp*1000),g_dev_status.panel_status);
		}
    }
}


void get_pressure_and_valvedegree() //获取风阀开度线程
{
	int bCali =1; //校准风阀开度AD
	uint8_t dir =0;
	uint16_t minAd =0,maxAd =0;
	uint16_t curval =0,lstval =0;
	int beginTime =0,endTime =0;
	double last_degree =-9999;
	float in3_r = 0.0;
	float in3_temp = 0.0;
	OMIP_LOG_INFO("%s task(%d) start!!!", __FUNCTION__, LOS_CurTaskIDGet());
	pca9555_in5_init();
	memset(&g_cali_data,0,sizeof(g_cali_data));
	memset(&g_dev_status,0,sizeof(g_dev_status));
	vav_read_flash_status(); //读取FLASH中保存的设备状态
	lstval =ad7708_read_value(USR_CHANNEL1);
	OMIP_LOG_INFO("Orientation calibration");
	MOTOR_CTL(dir,0);
	int lstTime =LOS_Tick2MS(LOS_TickCountGet());
	int ntc_r_lstTime = lstTime;
	int curTime =beginTime =lstTime;	
	while (true)
	{
		LOS_TaskDelay(50);
		g_dev_status.pressure =read_pressure(); //读取压差传感器数据
		curTime = LOS_Tick2MS(LOS_TickCountGet());
		
		if(abs(curTime - ntc_r_lstTime) > 5000){
			ntc_r_lstTime = curTime;
			in3_r = get_in3_resistor();
			in3_temp = resistor_to_temp_math(in3_r);
			if(in3_temp > 0 && in3_temp < 50) {
				g_dev_status.panel_env_temp = in3_temp;
				//OMIP_LOG_DEBUG("IN3 ntc20k R:%d, T:%d(x100)", (int)in3_r, (int)(in3_temp*100));
				MCU_LOG(MCU_LOG_INFO_FLASH, "IN3 ntc20k R:%d, T:%d(x100)", (int)in3_r, (int)(in3_temp*100));
			}
		}
		if(1 == bCali)
		{
			if(abs(curTime -lstTime) >3000) //每3秒读一次模拟值
			{
				curval =ad7708_read_value(USR_CHANNEL1);
				OMIP_LOG_DEBUG("curvalue:%u,lstval:%u,dir:%u\r\n", curval, lstval, dir);
				lstTime =curTime;
				if(abs(curval - lstval) < 20) //阀门已经到达限位
				{
					minAd =curval;
					bCali =2;
					dir =!dir; //阀门标志反向
					vav_motor_stop(); //阀门停止，用于放电
				}
				lstval = curval;
			}
		}
		else if(2 ==bCali)
		{
			if(abs(curTime -lstTime) >8000) //等待8s,待电机放电完再进行反方向转
			{
				lstTime =curTime;
				MOTOR_CTL(dir,0); //阀门反向转
				OMIP_LOG_INFO("Forward calibration\r\n");
				bCali =3;
			}
		}
		else if(3 ==bCali)
		{
			if(abs(curTime -lstTime) >3000)
			{
				curval =ad7708_read_value(USR_CHANNEL1);
				OMIP_LOG_DEBUG("curvalue:%u,lstval:%u,dir:%u\r\n",curval,lstval,dir);
				lstTime =curTime;
				if(abs(curval -lstval) <20) //阀门已经到达限位
				{
					maxAd =curval;
					bCali =0;
					endTime =curTime;
					vav_motor_stop();
					g_cali_data.valve_ad_max = maxAd>minAd?maxAd:minAd;
					g_cali_data.valve_ad_min = minAd<maxAd?minAd:maxAd;
					g_cali_data.is_calied =1;
					vav_add_sum_count(2);
					vav_add_sum_degree(150.0f);
					OMIP_LOG_INFO("valve_ad_max:%u,valve_ad_min:%u(%u,%u)\r\n",g_cali_data.valve_ad_max,g_cali_data.valve_ad_min,beginTime,endTime);
				}
				lstval = curval;
			}
		}  
		else
		{
			g_dev_status.valve_degree =get_valve_degree();
			float fAbsDiff =(float)fabs(last_degree-g_dev_status.valve_degree);
			if(abs(curTime-lstTime)>60000 || (fAbsDiff >=1 && abs(curTime-lstTime)>10000)) //打印风阀开度值
			{
				lstTime =curTime;
				if(fAbsDiff >=1 && last_degree>=0) vav_add_sum_degree(fAbsDiff);
				last_degree =g_dev_status.valve_degree;
				OMIP_LOG_INFO("valve degree:%d(x1000), sum:%d(x1000), pressure:%ld.\r\n", (int)(g_dev_status.valve_degree*1000),(int)(g_sava_status.sum_degree*1000),(int)g_dev_status.pressure);
			}
		}
	}
}

void get_pressure_and_valvedegree_thread() //获取风阀角度的线程
{
	static UINT32 TskHandle_get_degree; //获取风阀角度的线程ID
	UINT32 uwRet =LOS_OK;                                           //临时变量，用来返回liteos提供的api的操作结果
	TSK_INIT_PARAM_S task_pressure_and_valvedegree_operation_branch; //任务初始化所需的参数-结构体，可临时变量
	//LOS_TaskLock();                                                //锁任务调度,防止一创建就跑那个任务去了,如果不在任务/进程里就不用锁
	task_pressure_and_valvedegree_operation_branch.usTaskPrio =23;                             		//任务优先级，越小越优先  0-31
	task_pressure_and_valvedegree_operation_branch.pcName ="get_pressure_and_valvedegree_thread";	//任务名，暂时没用，但别重复
	task_pressure_and_valvedegree_operation_branch.pfnTaskEntry =(TSK_ENTRY_FUNC)get_pressure_and_valvedegree; //任务函数名
	task_pressure_and_valvedegree_operation_branch.uwStackSize =0x800;
	uwRet = LOS_TaskCreate(&TskHandle_get_degree, &task_pressure_and_valvedegree_operation_branch);	//创建任务
	if(uwRet !=LOS_OK) {
		OMIP_LOG_ERROR_FLASH("get_pressure_and_valvedegree task failed! ret=0x%x\r\n", uwRet); //失败
	}
	else {
		OMIP_LOG_INFO("get_pressure_and_valvedegree task success.\r\n");
	}
}

void get_paneldata() //获取面板数据任务
{
	static UINT32 TskHandle_paneldata; //获取面板数据任务线程ID
	UINT32 uwRet =LOS_OK;                               //临时变量，用来返回liteos提供的api的操作结果
	TSK_INIT_PARAM_S task_paneldata_operation_branch; 	//任务初始化所需的参数-结构体，可临时变量
	
	//LOS_TaskLock();                                 	//锁任务调度,防止一创建就跑那个任务去了,如果不在任务/进程里就不用锁
	task_paneldata_operation_branch.usTaskPrio =23;                          	//任务优先级，越小越优先  0-31
	task_paneldata_operation_branch.pcName ="get_paneldata";                	//任务名，暂时没用，但别重复
	task_paneldata_operation_branch.pfnTaskEntry =(TSK_ENTRY_FUNC)mode_switch;	//任务函数名
	task_paneldata_operation_branch.uwStackSize =0x800;
	uwRet = LOS_TaskCreate(&TskHandle_paneldata, &task_paneldata_operation_branch); //创建任务
	if(uwRet !=LOS_OK) {
		OMIP_LOG_ERROR_FLASH("get_paneldata task failed! ret=0x%x\r\n",uwRet); //失败 
	}
	else {
		OMIP_LOG_INFO("get_paneldata task success.\r\n");
	}
	//LOS_TaskUnlock();  //解锁任务调度
	return;
}
  
void mode_switch() //判断主从设备
{
    uint8_t data =0;
	OMIP_LOG_INFO("%s task(%d) start!!!", __FUNCTION__, LOS_CurTaskIDGet());
    LOS_TaskLock();
    get_switch(&data);
    LOS_TaskUnlock();
    g_mode = (data & 0x80);
    OMIP_LOG_INFO("g_mode: %s(0x%X)\r\n", (g_mode == MASTER?"MASTER":"SLAVE"),g_mode);
	if(g_mode == MASTER) 	worker_thread_master(); //是主设备
	else if(g_mode == SLAVE)	worker_thread_slave();	//是从设备
}

void vav_set_sys_status_led(uint8_t sign)
{
	if(sign ==0) 		{LED_SYS_NORMAL_(LED_CLOSE); LED_SYS_FAULT_(LED_OPEN);}
	else if(sign ==1)	{LED_SYS_NORMAL_(LED_OPEN); LED_SYS_FAULT_(LED_CLOSE);}
}

void vav_read_flash_status() //读取FLASH中保存的设备状态
{
    w25flash_t *flash_sta =file_addr_init("devstatus",FILE_DEV_STA_ADDR,FILE_DEV_STA_SIZE);
    flash_sta->buff = malloc(sizeof(uint8_t)*flash_sta->size);
    read_data_from_file(flash_sta);
	SAVE_STATUS *pSaveStatus =(SAVE_STATUS *)flash_sta->buff;
	if(strcmp(pSaveStatus->flash_sign,"devstatus")==0) //flash中已经写入过
	{
		memcpy(&g_sava_status,pSaveStatus,sizeof(SAVE_STATUS));
	}
	else //flash中还不存在
	{
		memset(&g_sava_status,0,sizeof(g_sava_status));
		strcpy(g_sava_status.flash_sign,"devstatus");
	}
	free_w25flash_t(&flash_sta);
}

void vav_write_flash_status() //将设备状态写入FLASH中保存
{
	w25flash_t *flash_sta = file_addr_init("devstatus",FILE_DEV_STA_ADDR,FILE_DEV_STA_SIZE);
	flash_sta->buff = malloc(sizeof(uint8_t)*flash_sta->size);
	memcpy(flash_sta->buff,&g_sava_status,sizeof(SAVE_STATUS));
	save_data_to_file(flash_sta); //写入flash
	free_w25flash_t(&flash_sta);
}


double	vav_get_pressure()							{return g_dev_status.pressure;}
float	vav_get_panel_set_temp()					{return g_dev_status.panel_set_temp;}

void vav_set_panel_set_temp(float set_temp)					
{
	omip_printf(OMIP_DEBUG_UPLOAD, "set panel temp(%d/10)\r\n", (int)set_temp*10);
	g_dev_status.panel_set_temp_tag = set_temp;
}
float	vav_get_panel_env_temp()					{return g_dev_status.panel_env_temp;}
int		vav_get_panel_status()						{return g_dev_status.panel_status;}
void vav_set_panel_status(int status)
{
	if(status == 1 || status == 0) {
		omip_printf(OMIP_DEBUG_UPLOAD, "set panel status(%d)\r\n", status);
		g_dev_status.panel_status_tag =  status;
	}
}

int		vav_get_panel_unit()						{return g_dev_status.panel_unit;}
double  vav_get_valve_degree()						{return g_dev_status.valve_degree;}
uint8_t vav_get_panel_set_temp_err()				
{
	if(g_dev_status.panel_set_temp_err) {
		printf("[%s:%d]panel_set_temp_err:%d\r\n",__FUNCTION__,__LINE__,g_dev_status.panel_set_temp_err);
	}
	return g_dev_status.panel_set_temp_err;
}

uint8_t vav_get_panel_env_temp_err()			
{
	if(g_dev_status.panel_env_temp_err) {
		printf("[%s:%d]panel_env_temp_err:%d\r\n",__FUNCTION__,__LINE__,g_dev_status.panel_env_temp_err);
	}
	return g_dev_status.panel_env_temp_err;
}

uint8_t vav_get_panel_status_err()					
{
	if(g_dev_status.panel_status_err) {
		printf("[%s:%d]panel_status_err:%d\r\n",__FUNCTION__,__LINE__,g_dev_status.panel_status_err);
	}
	return g_dev_status.panel_status_err;
}
uint8_t vav_read_valve_cali_status()				{return g_cali_data.is_calied;} //读取风阀开度校准状态

float	vav_get_sum_degree()						{return g_sava_status.sum_degree;}
int		vav_get_sum_count()							{return g_sava_status.sum_count;}
void	vav_add_sum_degree(float fDegree)			{g_sava_status.sum_degree =g_sava_status.sum_degree +fDegree; g_sava_status.is_changed =1;}
void	vav_add_sum_count(uint32_t iCount)			{g_sava_status.sum_count =g_sava_status.sum_count +iCount; g_sava_status.is_changed =1;}
int		vav_sumsta_ischanged()						{int ret =g_sava_status.is_changed; g_sava_status.is_changed =0; return ret;}

void sync_panel_err(uint16_t reg, uint8_t err)
{
	switch (reg)
	{
	case 0x0d:
		g_dev_status.panel_env_temp_err = err; 
		break;
	case 0x05:
		g_dev_status.panel_set_temp_err = err; 
		break;
	case 0x02:
		g_dev_status.panel_status_err = err; 
		break;
	default:
		OMIP_LOG_ERROR( "Unknown panel register(0x%04x)!!!", reg);
		break;
	}
	return;
}


void sync_panel_data(uint16_t reg, int value)
{
	OMIP_LOG_DEBUG( "panel register(0x%04x), value:%d .", reg, value);
	switch (reg)
	{
	case 0x0d:
		g_dev_status.panel_env_temp_err = 0; 
		g_dev_status.panel_env_temp = value / 10.0f;
		break;
	case 0x05:
		g_dev_status.panel_set_temp_err = 0; 
		g_dev_status.panel_set_temp = value / 10.0f;
		break;
	case 0x02:
		g_dev_status.panel_status_err = 0; 
		g_dev_status.panel_status = value;
		break;
	case 0x0C:
		g_dev_status.panel_unit = value; 
		break;
	default:
		OMIP_LOG_ERROR( "Unknown panel register(0x%04x)!!!", reg);
		break;
	}
	
	return;
}


